package com.facebook.fresco.samples.showcase.imagepipeline;

import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import com.facebook.fresco.samples.showcase.ResourceTable;
import com.facebook.fresco.samples.showcase.ShowcaseApplication;
import com.facebook.fresco.samples.showcase.annotation.Nullable;
import com.facebook.fresco.samples.showcase.imagepipeline.widget.ResizableStackLayout;
import com.facebook.fresco.samples.showcase.misc.ImageUriProvider;
import com.facebook.imagepipeline.common.ImageDecodeOptionsBuilder;
import com.facebook.imagepipeline.common.ResizeOptions;
import com.facebook.imagepipeline.request.ImageRequest;
import com.facebook.imagepipeline.request.ImageRequestBuilder;
import com.oszc.bbhmlibrary.utils.LogUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.ComponentContainer;
import ohos.agp.window.dialog.ListDialog;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import ohos.utils.net.Uri;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class ImagePipelineResizingAbility extends Ability {
    private final SizeEntry[] SPINNER_ENTRIES_SIZE =
            new SizeEntry[] {
                    new SizeEntry(null),
                    new SizeEntry(ResizeOptions.forDimensions(2560, 1440)),
                    new SizeEntry(ResizeOptions.forDimensions(1920, 1080)),
                    new SizeEntry(ResizeOptions.forDimensions(1200, 1200)),
                    new SizeEntry(ResizeOptions.forDimensions(720, 1280)),
                    new SizeEntry(ResizeOptions.forSquareSize(800)),
                    new SizeEntry(ResizeOptions.forDimensions(800, 600)),
                    new SizeEntry(ResizeOptions.forSquareSize(480)),
                    new SizeEntry(ResizeOptions.forDimensions(320, 240)),
                    new SizeEntry(ResizeOptions.forDimensions(240, 320)),
                    new SizeEntry(ResizeOptions.forDimensions(160, 90)),
                    new SizeEntry(ResizeOptions.forSquareSize(100)),
                    new SizeEntry(ResizeOptions.forSquareSize(64)),
                    new SizeEntry(ResizeOptions.forSquareSize(16)),
            };

    private ImageFormatEntry[] mImageFormatEntries;

    private SimpleDraweeView mDraweeMain;
    private Button mSizeSpinner;
    private Button mFormatSpinner;
    private ResizableStackLayout stackLayout;

    private int mFormatSpinnerPosition = 0;
    private int mSizeSpinnerPosition = 0;
    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_layout_imagepipeline_resizing);

        setupImageFormatEntries(ShowcaseApplication.imageUriProvider);

        mDraweeMain = (SimpleDraweeView) findComponentById(ResourceTable.Id_drawee_view);
        mSizeSpinner = (Button) findComponentById(ResourceTable.Id_spinner_size);
        mFormatSpinner = (Button) findComponentById(ResourceTable.Id_spinner_format);
        stackLayout = (ResizableStackLayout) findComponentById(ResourceTable.Id_frame_main);

        stackLayout.setSizeChangedListener((widthPx, heightPx) -> {
            ComponentContainer.LayoutConfig layoutConfig = mDraweeMain.getLayoutConfig();
            layoutConfig.width = widthPx;
            layoutConfig.height = heightPx;
            mDraweeMain.setLayoutConfig(layoutConfig);
        });

        mFormatSpinner.setClickedListener((view)->{
            new ListDialog(view.getContext()){
                {
                    List<ImageFormatEntry> entries = Collections.unmodifiableList(Arrays.asList(mImageFormatEntries));
                    Integer[] items = new Integer[mImageFormatEntries.length];
                    entries.stream().flatMap((Function<ImageFormatEntry, Stream<?>>) entry -> Stream.of(entry.nameResId)).collect(Collectors.toList()).toArray(items);
                    String[] strings = new String[mImageFormatEntries.length];
                    int index = 0;
                    for (Integer integer : items){
                        try {
                            strings[index] = getResourceManager().getElement(integer).getString();
                        } catch (IOException | NotExistException | WrongTypeException e) {
                            e.printStackTrace();
                        }
                        index++;
                    }
                    setSingleSelectItems(strings,mFormatSpinnerPosition);
                    setOnSingleSelectListener((iDialog, i) -> {
                        mFormatSpinnerPosition = i;
                        ImageFormatEntry entry = entries.get(i);
                        reloadImage();
                        mFormatSpinner.setText(entry.nameResId);
                        iDialog.destroy();
                    });
                }
            }.show();
        });
        mSizeSpinner.setClickedListener((view)->{
            new ListDialog(view.getContext()){
                {
                    List<SizeEntry> entries = Collections.unmodifiableList(Arrays.asList(SPINNER_ENTRIES_SIZE));
                    String[] items = new String[SPINNER_ENTRIES_SIZE.length];
                    entries.stream().flatMap((Function<SizeEntry, Stream<?>>) entry -> Stream.of(entry.toString())).collect(Collectors.toList()).toArray(items);
                    setSingleSelectItems(items,mSizeSpinnerPosition);
                    setOnSingleSelectListener((iDialog, i) -> {
                        mSizeSpinnerPosition = i;
                        SizeEntry entry = entries.get(i);
                        reloadImage();
                        mSizeSpinner.setText(entry.toString());
                        iDialog.destroy();
                    });
                }
            }.show();
        });

        ResizableStackLayout mSelectedRegion = (ResizableStackLayout) findComponentById(ResourceTable.Id_frame_main);
        mSelectedRegion.init(findComponentById(ResourceTable.Id_btn_resize));
        mFormatSpinner.setText(mImageFormatEntries[mFormatSpinnerPosition].nameResId);
        mSizeSpinner.setText(SPINNER_ENTRIES_SIZE[mSizeSpinnerPosition].toString());
        reloadImage();
    }
    private void setupImageFormatEntries(ImageUriProvider imageUriProvider) {
        mImageFormatEntries =
                new ImageFormatEntry[] {
                        new ImageFormatEntry(
                                ResourceTable.String_format_name_jpeg_landscape,
                                ImageUriProvider.createSampleUri(
                                        ImageUriProvider.ImageSize.XXL, ImageUriProvider.Orientation.LANDSCAPE,null)),
                        new ImageFormatEntry(
                                ResourceTable.String_format_name_jpeg_portrait,
                                ImageUriProvider.createSampleUri(
                                        ImageUriProvider.ImageSize.XXL, ImageUriProvider.Orientation.PORTRAIT,null)),
                        new ImageFormatEntry(
                                ResourceTable.String_format_name_png_landscape,
                                imageUriProvider.createPngUri(
                                        ImageUriProvider.Orientation.LANDSCAPE, ImageUriProvider.UriModification.NONE)),
                        new ImageFormatEntry(
                                ResourceTable.String_format_name_png_portrait,
                                imageUriProvider.createPngUri(
                                        ImageUriProvider.Orientation.PORTRAIT, ImageUriProvider.UriModification.NONE)),
                        new ImageFormatEntry(ResourceTable.String_format_name_webp, imageUriProvider.createWebpStaticUri()),
                        new ImageFormatEntry(
                               ResourceTable.String_format_name_animated_webp, imageUriProvider.createWebpAnimatedUri()),
                        new ImageFormatEntry(
                                ResourceTable.String_format_name_translucent_webp, imageUriProvider.createWebpTranslucentUri())
                };
    }
    private void reloadImage() {
        reloadImage(
                mImageFormatEntries[mFormatSpinnerPosition].uri,
                SPINNER_ENTRIES_SIZE[mSizeSpinnerPosition].resizeOptions);
    }

    private void reloadImage(Uri imageUri, @Nullable ResizeOptions resizeOptions) {
        LogUtil.error("ImagePipelineResizingAbility","imageUri = " + imageUri);
        final ImageRequest imageRequest =
                ImageRequestBuilder.newBuilderWithSource(imageUri)
                        .setResizeOptions(resizeOptions)
                        .setImageDecodeOptions(new ImageDecodeOptionsBuilder().build())
                        .build();
        final DraweeController draweeController =
                Fresco.newDraweeControllerBuilder()
                        .setOldController(mDraweeMain.getController())
                        .setImageRequest(imageRequest)
                        .build();
        mDraweeMain.setController(draweeController);
    }
    private class SizeEntry {

        final @Nullable ResizeOptions resizeOptions;

        SizeEntry(@Nullable ResizeOptions resizeOptions) {
            this.resizeOptions = resizeOptions;
        }

        @Override
        public String toString() {
            try {
                return resizeOptions == null
                        ? getResourceManager().getElement(ResourceTable.String_imagepipeline_resizing_disabled).getString()
                        : resizeOptions.toString();
            } catch (IOException | NotExistException | WrongTypeException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    private class ImageFormatEntry {

        final int nameResId;
        final Uri uri;

        private ImageFormatEntry(int nameResId, Uri uri) {
            this.nameResId = nameResId;
            this.uri = uri;
        }
    }
}
